package server

import (
	"context"
	"github.com/chromedp/chromedp"
	"log"
	"plan_go/domain"
	"time"
)

type ChromeScript struct {
}

func (com ChromeScript) waitForElementValue(sel, value string, isValueType bool) chromedp.Action {
	return chromedp.ActionFunc(func(ctx context.Context) error {
		ticker := time.NewTicker(500 * time.Millisecond)
		defer ticker.Stop()

		for {
			select {
			case <-ticker.C:
				var currentValue string
				var action chromedp.Action
				if isValueType {
					action = chromedp.Value(sel, &currentValue, chromedp.NodeVisible, chromedp.ByQuery)
				} else {
					action = chromedp.Text(sel, &currentValue, chromedp.NodeVisible, chromedp.ByQuery)
				}
				err := chromedp.Run(ctx, action)
				if err != nil {
					return err
				}
				println("currentValue:", currentValue)
				if currentValue == value {
					return nil
				}
			case <-ctx.Done():
				return ctx.Err()
			}
		}
	})
}

/**sovits 音频转换*/
//func (com ChromeScript) ConvertSovitsAudio(originFile string, outPutDir string) {
//
//	// 禁用chrome headless
//	opts := append(chromedp.DefaultExecAllocatorOptions[:],
//		chromedp.Flag("headless", false),
//	)
//	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
//	defer cancel()
//
//	// create chrome instance
//	ctx, cancel := chromedp.NewContext(
//		allocCtx,
//		chromedp.WithLogf(log.Printf),
//	)
//	defer cancel()
//
//	// create a timeout
//	ctx, cancel = context.WithTimeout(ctx, 24*3600*time.Second)
//	defer cancel()
//
//	windowInfo := domain.WindowInfo{Class: "#32770", Title: "打开", BindPara: domain.BindPara{Dx: "normal", Mouse: "windows3", Keyboard: "windows"}}
//	//sel := `//*[@id="component-14"]`
//	chromedp.Run(ctx,
//		chromedp.Navigate(`http://127.0.0.1:7860/`),
//		chromedp.WaitVisible(`//*[@id="component-14"]`),
//		chromedp.Click(`//*[@id="component-14"]`),                   // 使用 XPath 表达式点击按钮
//		chromedp.Sleep(1*time.Second),                               // 等待一段时间，确保选项列表已打开
//		chromedp.WaitVisible(`//*[@id="component-5"]/label/div`),    // 等待下拉选择框可见
//		chromedp.Click(`//*[@id="component-5"]/label/div`),          // 点击下拉选择框以打开选项列表
//		chromedp.Sleep(1*time.Second),                               // 等待一段时间，确保选项列表已打开
//		chromedp.Click(`//*[@id="component-5"]/label/div/ul/li[7]`), // 点击选项
//
//		com.waitForElementValue(`#component-6 > label > textarea`, "v1", true),
//
//		chromedp.Click(`#component-9 > label > div > div.wrap-inner.svelte-1ythexu`), // 点击配置文件下拉选择框以打开选项列表
//		chromedp.Sleep(1*time.Second),                                                // 等待一段时间，确保选项列表已打开
//		// sel:#component-9 > label > div > ul > li.item.svelte-1oas11n.selected xpath:
//		chromedp.Click(`//*[@id="component-9"]/label/div/ul/li[1]`), // 点击选项
//
//		chromedp.Click(`#component-12 > label > div > div.wrap-inner.svelte-1ythexu`), // 点击配置文件下拉选择框以打开选项列表
//		chromedp.Sleep(1*time.Second),                                                 // 等待一段时间，确保选项列表已打开
//		// sel:#component-9 > label > div > ul > li.item.svelte-1oas11n.selected xpath:
//		chromedp.Click(`//*[@id="component-12"]/label/div/ul/li`), // 点击选项
//		chromedp.Click(`//*[@id="component-15"]`),                 // 点击选项
//
//		chromedp.Sleep(1*time.Second), // 等待一段时间，确保加载动作先完成
//		com.waitForElementValue(`#component-16 > label > div > div.wrap-inner.svelte-1ythexu > span`, "ma", false), // 等待ma音色准备完成
//
//		chromedp.Click(`//*[@id="component-21"]/div[3]`, chromedp.NodeVisible), // 点击文件上传按钮
//		// 上传文件
//		chromedp.ActionFunc(func(ctx context.Context) error {
//			ExploreFileUpload(originFile, windowInfo)
//			return nil
//		}),
//		chromedp.Sleep(1*time.Second),                                   // 等待一段时间，确保上传文件加载动作先完成
//		chromedp.Click(`//*[@id="component-51"]`, chromedp.NodeVisible), // 点击转换按钮
//	)
//}

var ctxInstance *context.Context
var ctxCancelInstance context.CancelFunc

func GetCtx() (*context.Context, context.CancelFunc) {
	if nil != ctxInstance {
		return ctxInstance, ctxCancelInstance
	}
	// 禁用chrome headless 具体列表配置如下: https://peter.sh/experiments/chromium-command-line-switches/
	opts := append(chromedp.DefaultExecAllocatorOptions[:],
		chromedp.Flag("headless", false),
		chromedp.Flag("mute-audio", false), // 禁用静音
	)
	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)

	// create chrome instance
	ctx, cancel := chromedp.NewContext(
		allocCtx,
		chromedp.WithLogf(log.Printf),
	)

	// create a timeout
	ctx, cancel = context.WithTimeout(ctx, 24*3600*time.Second)
	ctxInstance = &ctx
	return &ctx, cancel
}

type TaskFunc func()

/**sovits 音频转换*/
func (com ChromeScript) ConvertSovitsAudioFirst(originFile string) {
	log.Println("ConvertSovitsAudioFirst start")
	ctx, _ := GetCtx()
	windowInfo := domain.WindowInfo{Class: "#32770", Title: "打开", BindPara: domain.BindPara{Dx: "normal", Mouse: "windows3", Keyboard: "windows"}}
	//sel := `//*[@id="component-14"]`
	chromedp.Run(*ctx,
		chromedp.Navigate(`http://127.0.0.1:7860/`),
		chromedp.WaitVisible(`//*[@id="component-14"]`),
		chromedp.Click(`//*[@id="component-14"]`),                   // 使用 XPath 表达式点击按钮
		chromedp.Sleep(1*time.Second),                               // 等待一段时间，确保选项列表已打开
		chromedp.WaitVisible(`//*[@id="component-5"]/label/div`),    // 等待下拉选择框可见
		chromedp.Click(`//*[@id="component-5"]/label/div`),          // 点击下拉选择框以打开选项列表
		chromedp.Sleep(1*time.Second),                               // 等待一段时间，确保选项列表已打开
		chromedp.Click(`//*[@id="component-5"]/label/div/ul/li[7]`), // 点击选项

		com.waitForElementValue(`#component-6 > label > textarea`, "v1", true),

		chromedp.Click(`#component-9 > label > div > div.wrap-inner.svelte-1ythexu`), // 点击配置文件下拉选择框以打开选项列表
		chromedp.Sleep(1*time.Second),                                                // 等待一段时间，确保选项列表已打开
		// sel:#component-9 > label > div > ul > li.item.svelte-1oas11n.selected xpath:
		chromedp.Click(`//*[@id="component-9"]/label/div/ul/li[1]`), // 点击选项

		chromedp.Click(`#component-12 > label > div > div.wrap-inner.svelte-1ythexu`), // 点击配置文件下拉选择框以打开选项列表
		chromedp.Sleep(1*time.Second),                                                 // 等待一段时间，确保选项列表已打开
		// sel:#component-9 > label > div > ul > li.item.svelte-1oas11n.selected xpath:
		chromedp.Click(`//*[@id="component-12"]/label/div/ul/li`), // 点击选项
		chromedp.Click(`//*[@id="component-15"]`),                 // 点击选项

		chromedp.Sleep(1*time.Second), // 等待一段时间，确保加载动作先完成
		com.waitForElementValue(`#component-16 > label > div > div.wrap-inner.svelte-1ythexu > span`, "ma", false), // 等待ma音色准备完成
		chromedp.Sleep(3*time.Second),
		chromedp.Click(`//*[@id="component-21"]/div[3]`, chromedp.NodeVisible), // 点击文件上传按钮
		// 上传文件
		chromedp.ActionFunc(func(ctx context.Context) error {
			ExploreFileUpload(originFile, windowInfo)
			return nil
		}),
		chromedp.Sleep(1*time.Second),                                   // 等待一段时间，确保上传文件加载动作先完成
		chromedp.Click(`//*[@id="component-51"]`, chromedp.NodeVisible), // 点击转换按钮
		chromedp.Sleep(3*time.Second),
	)
}

/**sovits 音频转换*/
func (com ChromeScript) ConvertSovitsAudioSecond(originFile string) {
	log.Println("ConvertSovitsAudioSecond start")
	ctx, _ := GetCtx()
	windowInfo := domain.WindowInfo{Class: "#32770", Title: "打开", BindPara: domain.BindPara{Dx: "normal", Mouse: "windows3", Keyboard: "windows"}}
	//sel := `//*[@id="component-14"]`
	chromedp.Run(*ctx,
		chromedp.Click(`//*[@id="component-21"]/div[3]/button[2]`, chromedp.NodeVisible), // 点击取消按钮
		chromedp.Sleep(1*time.Second),                                          // 等待一段时间，确保取消生效
		chromedp.Click(`//*[@id="component-21"]/div[3]`, chromedp.NodeVisible), // 点击文件上传按钮
		// 上传文件
		chromedp.ActionFunc(func(ctx context.Context) error {
			ExploreFileUpload(originFile, windowInfo)
			return nil
		}),
		chromedp.Sleep(1*time.Second),                                   // 等待一段时间，确保上传文件加载动作先完成
		chromedp.Click(`//*[@id="component-51"]`, chromedp.NodeVisible), // 点击转换按钮
		chromedp.Sleep(3*time.Second),
	)
}

/**sovits 音频转换*/
func (com ChromeScript) ConvertSovitsAudioYouHua(ch <-chan TaskFunc) {
	for task := range ch {
		task() // 调用闭包中的函数来执行任务
	}
}
